package com.uinnova.product.eam.service.impl;

import com.alibaba.fastjson.JSON;
import com.binary.core.exception.BinaryException;
import com.binary.jdbc.Page;
import com.uinnova.product.eam.dao.ArchFinalReviewExpertConfDao;
import com.uinnova.product.eam.dao.ArchFinalReviewExpertDetailConfDao;
import com.uinnova.product.eam.dto.SimpUserInfo;
import com.uinnova.product.eam.model.es.ArchFinalReviewExpertConf;
import com.uinnova.product.eam.model.es.ArchFinalReviewExpertDetailConf;
import com.uinnova.product.eam.service.PreReviewFinalExpertConfService;
import com.uinnova.product.eam.vo.PreReviewFinalExpertSaveVO;
import com.uino.api.client.permission.IUserApiSvc;
import com.uino.bean.permission.base.SysUser;
import com.uino.bean.permission.query.CSysUser;
import com.uino.dao.util.ESUtil;
import com.uino.util.sys.SysUtil;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.TermQueryBuilder;
import org.elasticsearch.index.query.TermsQueryBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

@Service
public class PreReviewFinalExpertConfSvcImpl implements PreReviewFinalExpertConfService {

    @Autowired
    private IUserApiSvc userApiSvc;

    @Autowired
    private ArchFinalReviewExpertConfDao archFinalReviewExpertConfDao;

    @Autowired
    private ArchFinalReviewExpertDetailConfDao archFinalReviewExpertDetailConfDao;

    @Override
    public Boolean save(List<PreReviewFinalExpertSaveVO> preReviewFinalExpertSaveVOs) {
        Assert.notEmpty(preReviewFinalExpertSaveVOs,"终审专家不能为空");
        Set<String> experts = new HashSet<>();
        for (PreReviewFinalExpertSaveVO preReviewFinalExpertSaveVO : preReviewFinalExpertSaveVOs) {
            if (StringUtils.isEmpty(preReviewFinalExpertSaveVO.getDomain())) {
                throw new BinaryException("领域不能为空");
            }
            if (CollectionUtils.isEmpty(preReviewFinalExpertSaveVO.getExpertList())) {
                throw new BinaryException("配置的领域专家名单不能为空");
            }
            experts.addAll(preReviewFinalExpertSaveVO.getExpertList());
        }
        List<SysUser> users = getUserByLoginCodes(experts);
        if (CollectionUtils.isEmpty(users) || experts.size() != users.size()) {
            throw new BinaryException("部分专家名单不存在，请刷新页面重试");
        }
        Map<String, SimpUserInfo> userInfoMap = users.stream().collect(Collectors.toMap(
                SysUser :: getLoginCode,e-> new SimpUserInfo(e.getLoginCode(),e.getUserName())
        ));
        Long archFinalReviewConfId = ESUtil.getUUID();
        String curUserLoginCode = SysUtil.getCurrentUserInfo().getLoginCode();
        ArchFinalReviewExpertConf finalConf = new ArchFinalReviewExpertConf();
        finalConf.setId(archFinalReviewConfId);
        finalConf.setVersion(getMaxVersion()+1);
        finalConf.setCreatorCode(curUserLoginCode);
        finalConf.setCreateTime(ESUtil.getNumberDateTime());
        finalConf.setModifierCode(curUserLoginCode);
        finalConf.setModifyTime(ESUtil.getNumberDateTime());
        List<ArchFinalReviewExpertDetailConf> finalExpertDetailConfList = new ArrayList<>();
        for (PreReviewFinalExpertSaveVO finalSaveVO : preReviewFinalExpertSaveVOs) {
            ArchFinalReviewExpertDetailConf finalExpertDetailConf = new ArchFinalReviewExpertDetailConf();
            finalExpertDetailConf.setId(finalSaveVO.getId() == null ? ESUtil.getUUID():finalSaveVO.getId());
            finalExpertDetailConf.setExpertConfId(archFinalReviewConfId);
            finalExpertDetailConf.setDomain(finalSaveVO.getDomain());
            finalExpertDetailConf.setExperts(finalSaveVO.getExpertList());
            if (!CollectionUtils.isEmpty(finalSaveVO.getExpertList())) {
                List<SimpUserInfo> finalExpertInfos = new ArrayList<>();
                finalSaveVO.getExpertList().forEach(expert -> {
                    finalExpertInfos.add(userInfoMap.get(expert));
                });
                finalExpertDetailConf.setExpertsInfos(finalExpertInfos);
            }
            if (finalSaveVO.getId() == null) {
                finalExpertDetailConf.setCreatorCode(curUserLoginCode);
                finalExpertDetailConf.setCreateTime(ESUtil.getNumberDateTime());
            }
            finalExpertDetailConf.setModifierCode(curUserLoginCode);
            finalExpertDetailConf.setModifyTime(ESUtil.getNumberDateTime());
            finalExpertDetailConfList.add(finalExpertDetailConf);
        }
        finalConf.setSnapShot(JSON.toJSONString(finalExpertDetailConfList));
        archFinalReviewExpertConfDao.saveOrUpdate(finalConf);
        Set<Long> existIds = preReviewFinalExpertSaveVOs.stream().map(PreReviewFinalExpertSaveVO :: getId).filter(Objects :: nonNull).collect(Collectors.toSet());
        if (!CollectionUtils.isEmpty(existIds)) {
            TermsQueryBuilder deleteQuery = QueryBuilders.termsQuery("id",existIds);
            archFinalReviewExpertDetailConfDao.deleteByQuery(deleteQuery,true);
        }
        archFinalReviewExpertDetailConfDao.saveOrUpdateBatch(finalExpertDetailConfList);
        return true;
    }

    @Override
    public void checkPre(List<PreReviewFinalExpertSaveVO> saveVOs) {
        Assert.notEmpty(saveVOs,"评审专家不能为空");
        Set<String> experts = new HashSet<>();
        for (PreReviewFinalExpertSaveVO saveVO : saveVOs) {
            if (StringUtils.isBlank(saveVO.getDomain())) {
                throw new BinaryException("领域不能为空");
            }
            if (CollectionUtils.isEmpty(saveVO.getExpertList())) {
                throw new BinaryException("至少配置一个领域专家名单");
            }
            experts.addAll(saveVO.getExpertList());
        }
        List<SysUser> users = getUserByLoginCodes(experts);
        if (CollectionUtils.isEmpty(users) || experts.size() != users.size()) {
            throw new BinaryException("部分专家名单不存在，请刷新页面重试");
        }
    }

    @Override
    public List<ArchFinalReviewExpertDetailConf> list() {
        Long maxVersion = getMaxVersion();
        if (maxVersion == 0L) {
            return new ArrayList<>();
        }
        TermQueryBuilder finalExpertConfQuery = QueryBuilders.termQuery("version",maxVersion);
        Page<ArchFinalReviewExpertConf> page = archFinalReviewExpertConfDao.getSortListByQuery(1, 1, finalExpertConfQuery, "createTime", false);
        ArchFinalReviewExpertConf finalExpertConf = page.getData().get(0);
        TermQueryBuilder finalExpertDetailConfQuery = QueryBuilders.termQuery("expertConfId",finalExpertConf.getId());
        Page<ArchFinalReviewExpertDetailConf> finalDetaiPage = archFinalReviewExpertDetailConfDao.getSortListByQuery(1, 3000, finalExpertDetailConfQuery, "createTime", false);
        if (CollectionUtils.isEmpty(finalDetaiPage.getData())) {
            return new ArrayList<>();
        }
        Set<String> experts = new HashSet<>();
        Map<String,SimpUserInfo> redundanceExpertMap = new ConcurrentHashMap<>();
        for (ArchFinalReviewExpertDetailConf finalDetailConf : finalDetaiPage.getData()) {
            if (!CollectionUtils.isEmpty(finalDetailConf.getExperts())) {
                experts.addAll(finalDetailConf.getExperts());
                redundanceExpertMap.putAll(finalDetailConf.getExpertsInfos().stream()
                        .collect(Collectors.toMap(SimpUserInfo::getLoginCode,e ->e,(k1,k2)->k1)));
            }
        }
        Map<String,SimpUserInfo> dbExpertMap = new ConcurrentHashMap<>();
        List<SysUser> users = getUserByLoginCodes(experts);
        if (!CollectionUtils.isEmpty(users)) {
            dbExpertMap = users.stream().collect(Collectors.toMap(SysUser::getLoginCode,
                    e -> new SimpUserInfo(e.getLoginCode(),e.getUserName()),(k1,k2)-> k1));
        }
        List<ArchFinalReviewExpertDetailConf> infos = new ArrayList<>();
        for (ArchFinalReviewExpertDetailConf info : finalDetaiPage.getData()) {
            List<SimpUserInfo> expertInfos = new ArrayList<>();
            if (!CollectionUtils.isEmpty(info.getExperts())) {
                for (String expert : info.getExperts()) {
                    String userName = dbExpertMap.getOrDefault(expert,redundanceExpertMap.get(expert)).getUserName();
                    expertInfos.add(new SimpUserInfo(expert,userName));
                }
            }
            info.setExpertsInfos(expertInfos);
            infos.add(info);
        }
        return infos;
    }

    private Long getMaxVersion() {
        Page<ArchFinalReviewExpertConf> page = archFinalReviewExpertConfDao.getSortListByQuery(1, 1, QueryBuilders.boolQuery(), "version", false);
        return CollectionUtils.isEmpty(page.getData()) ? 0L : page.getData().get(0).getVersion();
    }

    private List<SysUser> getUserByLoginCodes(Set<String> loginCodes) {
        CSysUser cdt = new CSysUser();
        cdt.setLoginCodes(loginCodes.toArray(new String[loginCodes.size()]));
        return userApiSvc.getSysUserByCdt(cdt);
    }
}
